#ifndef __LSZ_ANYCONTAINER_H__
#define __LSZ_ANYCONTAINER_H__

#include "LszTypes.h"
#include "LszAny.h"
#include <climits>
#include <cfloat>

#pragma warning(disable : 4512)
#pragma warning(disable : 4786)

namespace	Lsz
{

struct AnyVector_p;

typedef bool (*any_vector_sort_comp) (const Any&first, const Any&second);
class LSZCORE_EXPORT	AnyVector
{
public:
	AnyVector();
	AnyVector(const AnyVector& right);

	explicit			AnyVector(const Any& v0);
	AnyVector(const Any& v0, const Any& v1);
	AnyVector(const Any& v0, const Any& v1, const Any& v2);
	AnyVector(const Any& v0, const Any& v1, const Any& v2, const Any& v3);
	AnyVector(const Any& v0, const Any& v1, const Any& v2, const Any& v3, const Any& v4);
	AnyVector(const Any& v0, const Any& v1, const Any& v2, const Any& v3, const Any& v4, const Any& v5);
	AnyVector(const Any& v0, const Any& v1, const Any& v2, const Any& v3, const Any& v4, const Any& v5, const Any& v6);
	AnyVector(const Any& v0, const Any& v1, const Any& v2, const Any& v3, const Any& v4, const Any& v5, const Any& v6, const Any& v7);
	AnyVector(const Any& v0, const Any& v1, const Any& v2, const Any& v3, const Any& v4, const Any& v5, const Any& v6, const Any& v7, const Any& v8);
	AnyVector(const Any& v0, const Any& v1, const Any& v2, const Any& v3, const Any& v4, const Any& v5, const Any& v6, const Any& v7, const Any& v8, const Any& v9);
	AnyVector(const Any& v0, const Any& v1, const Any& v2, const Any& v3, const Any& v4, const Any& v5, const Any& v6, const Any& v7, const Any& v8, const Any& v9, const Any& v10);

	virtual				~AnyVector();

	AnyVector &operator =(const AnyVector& right);

	void				swap(AnyVector& other);
	Any&				at(int index) const;
	int					size() const;

	Any&				append(const Any& value);
	AnyDict&			append(const AnyDict& value);
	AnyVector&			append(const AnyVector& value);

	void				extend(const AnyVector& other);

	void				insert(const Any& value, const int pos);

	Any					popBack();

	void				resize(int newSize);

	Any&				front();
	const Any&			front() const;
	Any&				back();
	const Any&			back() const;

	AnyVector &operator <<(const Any& val)	{ append(val); return *this; }

	int					indexOf(const Any& value, int last = -1) const;

	inline int find(const Any& value, int last = -1) const
	{
		return indexOf(value, last);
	}

	inline bool contains(const Any& value) const
	{
		return -1 != indexOf(value);
	}

	int				ffind(double value, double eps = 1e-12) const;
	int				nearest(const Any& value) const;
	void			remove(int index);
	void			removeMany(const AnyVector& indices);
	Any &operator	[](int index) const;
	void			set(int index, const Any& val);

	void			sort(bool desc = false);
	void			sort(any_vector_sort_comp comp);
	void			sortDicts(const char* key);
	void			clear();

	int				isValid() const;

	bool operator	==(const AnyVector& right) const;
	bool operator!=(const AnyVector& right) const
	{
		return !operator ==(right);
	}

	Any							join(const Any& separator) const;
	bool						empty() const;
	static AnyVector			split(const Any& string, const Any& separator);
	bool						isNull() const;
	static const AnyVector&		null();
	Any*						descendant(const char* pathFmt, ...) const;

private:
	AnyVector_p*	_x;
};

#define AnyVector_Null	(AnyVector::null())

class					AnyDict_p;

class LSZCORE_EXPORT	AnyDict
{
public:
	AnyDict();
	AnyDict(const AnyDict& right);
	virtual				~AnyDict();

	AnyDict(const char* k0, const Any& v0);
	AnyDict(const char* k0, const Any& v0, const char* k1, const Any& v1);
	AnyDict(const char* k0, const Any& v0, const char* k1, const Any& v1, const char* k2, const Any& v2);
	AnyDict(const char* k0, const Any& v0, const char* k1, const Any& v1, const char* k2, const Any& v2, const char* k3, const Any& v3);
	AnyDict(const char* k0, const Any& v0, const char* k1, const Any& v1, const char* k2, const Any& v2, const char* k3, const Any& v3, const char* k4, const Any& v4);
	AnyDict
	(
		const char*		k0,
		const Any&		v0,
		const char*		k1,
		const Any&		v1,
		const char*		k2,
		const Any&		v2,
		const char*		k3,
		const Any&		v3,
		const char*		k4,
		const Any&		v4,
		const char*		k5,
		const Any&		v5
	);
	AnyDict
	(
		const char*		k0,
		const Any&		v0,
		const char*		k1,
		const Any&		v1,
		const char*		k2,
		const Any&		v2,
		const char*		k3,
		const Any&		v3,
		const char*		k4,
		const Any&		v4,
		const char*		k5,
		const Any&		v5,
		const char*		k6,
		const Any&		v6
	);
	AnyDict
	(
		const char*		k0,
		const Any&		v0,
		const char*		k1,
		const Any&		v1,
		const char*		k2,
		const Any&		v2,
		const char*		k3,
		const Any&		v3,
		const char*		k4,
		const Any&		v4,
		const char*		k5,
		const Any&		v5,
		const char*		k6,
		const Any&		v6,
		const char*		k7,
		const Any&		v7
	);

	AnyDict &operator	=(const AnyDict& right);
	void				swap(AnyDict& other);
	void				update(const AnyDict& other);
	Any &operator		[](const char* key) const;

	int					size() const;
	Any&				get(const char* key) const;
	Any&				set(const char* key, const Any& val);
	Any&				set(const char* key, const AnyDict& val);
	Any&				set(const char* key, const AnyVector& val);
	void				clear();
	void				remove(const char* Key);
	void				getKeyVal(int index, Any& key, Any& val) const;

	bool				isSet(const char* key) const;
	bool contains(const char* key) const
	{
		return isSet(key);
	}

	const char*		getKey(int index) const;
	Any&			getVal(int index) const;

	bool operator	==(const AnyDict& right) const;
	bool operator!=(const AnyDict& right) const
	{
		return !operator ==(right);
	}

	bool	empty() const;
	int		find(const Any& val) const;

	struct Entry
	{
		Entry();
		Entry (const char*k, const Any&v);
		Entry (const Entry&other);
		const char*		key;
		const Any&		val;
	};

	Entry	getEntry(int pos) const;
	inline Entry at(int pos) const
	{
		return getEntry(pos);
	}

	bool					isNull() const;

	static const AnyDict&	null();
	Any*					descendant(const char* pathFmt, ...) const;

	inline int32_t getInt32(const char* key, int32_t dfl = INT_MIN) const
	{
		return get(key).asInt32(dfl);
	}

	inline int64_t getInt64(const char* key, int64_t dfl = LLONG_MIN) const
	{
		return get(key).asInt64(dfl);
	}

	inline double getDouble(const char* key, double dfl = DBL_MIN) const
	{
		return get(key).asDouble(dfl);
	}

	inline double getFloat(const char* key, double dfl = DBL_MIN) const
	{
		return get(key).asDouble(dfl);
	}

	inline const char* getString(const char* key, const char* dfl = 0) const
	{
		return get(key).asString(dfl);
	}

	inline const McWChar* getWString(const char* key, const McWChar* dfl = 0) const
	{
		return get(key).asWString(dfl);
	}

	inline AnyVector& getVector(const char* key, const AnyVector& dfl = AnyVector_Null) const
	{
		Any&	v = get(key);
		return v.isVector() ? v.asVector() : const_cast<AnyVector&>(dfl);
	}

	inline AnyDict& getDict(const char* key, const AnyDict& dfl = null()) const
	{
		Any&	v = get(key);
		return v.isDict() ? v.asDict() : const_cast<AnyDict&>(dfl);
	}

	inline void* getPtr(const char* key, void* dfl = 0) const
	{
		Any&	v = get(key);
		return v.isGeneric() ? v.asGeneric() : dfl;
	}

private:
	AnyDict_p*	_x;
};

#define AnyDict_Null	(AnyDict::null())

}

#endif // __LSZ_ANYCONTAINER_H__
